0141. 环形链表【简单】
1. 📝 题目描述
给你一个链表的头节点 head,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递。仅仅是为了标识链表的实际情况。
- 如果链表中存在环,则返回
true - 否则,返回
false
示例 1:

txt
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。1
2
3
2
3
示例 2:

txt
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。1
2
3
2
3
示例 3:

txt
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。1
2
3
2
3
提示:
- 链表中节点的数目范围是
[0, 10^4] -10^5 <= Node.val <= 10^5pos为-1或者链表中的一个有效索引。
进阶:你能用 O(1)(即,常量)内存解决此问题吗?
2. 🎯 s.1 - Floyd 判圈算法
js
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var hasCycle = function (head) {
// 边界情况:空链表或只有一个节点
if (!head || !head.next) {
return false
}
// 初始化快慢指针
let slow = head
let fast = head.next
// 快慢指针遍历链表
while (slow !== fast) {
// 如果快指针到达链表末尾,说明无环
if (!fast || !fast.next) {
return false
}
// 移动指针
slow = slow.next // 慢指针每次移动一步
fast = fast.next.next // 快指针每次移动两步
}
// 如果快慢指针相遇,说明有环
return true
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
- 时间复杂度:
,其中 n 是链表的节点数,快慢指针最多遍历链表两次 - 空间复杂度:
,只使用了常数级别的额外空间
算法思路:
- 使用快慢指针,慢指针每次移动一步,快指针每次移动两步
- 如果链表有环,快指针最终会追上慢指针(相遇)
- 如果链表无环,快指针会先到达链表末尾(null)